bitkeeper revision 1.603 (3fb3bacevrb8jueJUVr6_fTdAFNH3A)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 13 Nov 2003 17:09:34 +0000 (17:09 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 13 Nov 2003 17:09:34 +0000 (17:09 +0000)
ac_timer.h, schedule.c, network.c, ac_timer.c:
  Cleaned up ac_timer interface, and fixed a bug in the softirq handler.

xen/common/ac_timer.c
xen/common/network.c
xen/common/schedule.c
xen/include/xeno/ac_timer.h

index e456e83624d78cc9a364621ed8ed7c59dc8e2b14..c3d2f51b3739c5ea503d71e9852aef513acf50c0 100644 (file)
@@ -246,6 +246,7 @@ static void ac_timer_softirq_action(struct softirq_action *a)
     int              cpu = smp_processor_id();
     struct ac_timer *t, **heap;
     s_time_t         now;
+    void             (*fn)(unsigned long);
 
     spin_lock_irq(&ac_timers[cpu].lock);
     
@@ -257,12 +258,15 @@ static void ac_timer_softirq_action(struct softirq_action *a)
                 ((t = heap[1])->expires < (now + TIMER_SLOP)) )
         {
             remove_entry(heap, t);
-                        
-            spin_unlock_irq(&ac_timers[cpu].lock);
-            if ( t->function != NULL ) 
-                t->function(t->data);
-            spin_lock_irq(&ac_timers[cpu].lock);
-            
+
+            if ( (fn = t->function) != NULL )
+            {
+                unsigned long data = t->data;
+                spin_unlock_irq(&ac_timers[cpu].lock);
+                (*fn)(data);
+                spin_lock_irq(&ac_timers[cpu].lock);
+            }
+
             /* Heap may have grown while the lock was released. */
             heap = ac_timers[cpu].heap;
         }
index 367790644a1989c2b6565184800ea5be9496b692..02b6f57580d8f976d94aff5dfabf011162df9398 100644 (file)
@@ -107,7 +107,7 @@ net_vif_t *create_net_vif(int domain)
 
     new_vif->credit_bytes = new_vif->remaining_credit = ~0UL;
     new_vif->credit_usec  = 0UL;
-    init_ac_timer(&new_vif->credit_timeout, 0);
+    init_ac_timer(&new_vif->credit_timeout);
 
     if ( (p->domain == 0) && (dom_vif_idx == 0) )
     {
index 5f22ec8013ba0e00d31d2b184344cfb296e8f76a..5997b276a27415d9553846434558a7ceac364dfc 100644 (file)
@@ -613,18 +613,21 @@ void __init scheduler_init(void)
         spin_lock_init(&schedule_data[i].lock);
         schedule_data[i].curr = &idle0_task;
         
-        init_ac_timer(&schedule_data[i].s_timer, i);
+        init_ac_timer(&schedule_data[i].s_timer);
+        schedule_data[i].s_timer.cpu      = i;
         schedule_data[i].s_timer.data     = 2;
         schedule_data[i].s_timer.function = &sched_timer;
 
-        init_ac_timer(&fallback_timer[i], i);
+        init_ac_timer(&fallback_timer[i]);
+        fallback_timer[i].cpu      = i;
         fallback_timer[i].data     = 0;
         fallback_timer[i].function = &fallback_timer_fn;
     }
 
     schedule_data[0].idle = &idle0_task;
 
-    init_ac_timer(&v_timer, 0);
+    init_ac_timer(&v_timer);
+    v_timer.cpu      = 0;
     v_timer.data     = 0;
     v_timer.function = &virt_timer;
 }
index 987fbeed3390f7ec0f5a2f0adb2384eecbc8d5d0..3689662e95001c5f86f465059273b9e0c7d80d10 100644 (file)
 #ifndef _AC_TIMER_H_
 #define _AC_TIMER_H_
 
-#include <xeno/time.h> /* include notion of time */
-
-/*
- * The Xen Hypervisor provides two types of timers:
- *
- * - Linux style, jiffy based timers for legacy code and coarse grain timeouts
- *   These are defined in ./include/xeno/timer.h and implemented in
- *   ./common/timer.c. Unlike in Linux they are executed not on a periodic
- *   timer interrupt but "occasionally" with somewhat lesser accuracy.
- *  
- * - accurate timers defined in this file and implemented in
- *   ./common/ac_timer.c. These are implemented using a programmable timer
- *   interrupt and are thus as accurate as the hardware allows. Where possible
- *   we use the local APIC for this purpose. However, this fact is hidden
- *   behind a architecture independent layer.
- *   accurate timers are programmed using system time.
- * 
- * The interface to accurate timers is very similar to Linux timers with the
- * exception that the expires value is not expressed in jiffies but in ns from
- * boot time.  Its implementation however, is entirely different.
- */
+#include <xeno/time.h>
 
 struct ac_timer {
-    s_time_t         expires;   /* system time time out value */
+    /*
+     * PUBLIC FIELDS
+     */
+    /* System time expiry value (nanoseconds since boot). */
+    s_time_t         expires;
+    /* CPU on which this timer will be installed and executed. */
+    unsigned int     cpu;
+    /* On expiry, '(*function)(data)' will be executed in softirq context. */
     unsigned long    data;
     void             (*function)(unsigned long);
-    unsigned int     cpu;
+
+    /*
+     * PRIVATE FIELDS
+     */
     unsigned int     heap_offset;
 };
 
-/* interface for "clients" */
-extern void add_ac_timer(struct ac_timer *timer);
-extern void rem_ac_timer(struct ac_timer *timer);
-extern void mod_ac_timer(struct ac_timer *timer, s_time_t new_time);
-static __inline__ void init_ac_timer(struct ac_timer *timer, int cpu)
+/*
+ * This function can be called for any CPU from any CPU in any context.
+ * It initialises the private fields of the ac_timer structure.
+ */
+static __inline__ void init_ac_timer(struct ac_timer *timer)
 {
-    timer->cpu = cpu;
     timer->heap_offset = 0;
 }
-/* check if ac_timer is active, i.e., on the list */
+
+/*
+ * This function can be called for any CPU from any CPU in any context.
+ * It returns TRUE if the given timer is on a timer list.
+ */
 static __inline__ int active_ac_timer(struct ac_timer *timer)
 {
     return (timer->heap_offset != 0);
 }
 
-/* interface used by programmable timer, implemented hardware dependent */
-extern int  reprogram_ac_timer(s_time_t timeout);
+/*
+ * This function can be called for any CPU from any CPU in any context, BUT:
+ *  -- The private fields must have been initialised (ac_timer_init).
+ *  -- All public fields must be initialised.
+ *  -- The timer must not currently be on a timer list.
+ */
+extern void add_ac_timer(struct ac_timer *timer);
+
+/*
+ * This function can be called for any CPU from any CPU in any context, BUT:
+ *  -- The private fields must have been initialised (ac_timer_init).
+ *  -- All public fields must be initialised.
+ *  -- The timer must currently be on a timer list.
+ */
+extern void rem_ac_timer(struct ac_timer *timer);
+
+/*
+ * This function can be called for any CPU from any CPU in any context, BUT:
+ *  -- The private fields must have been initialised (ac_timer_init).
+ *  -- All public fields must be initialised.
+ */
+extern void mod_ac_timer(struct ac_timer *timer, s_time_t new_time);
+
+
+/*
+ * PRIVATE DEFINITIONS
+ */
+
+extern int reprogram_ac_timer(s_time_t timeout);
 
 #endif /* _AC_TIMER_H_ */